package com.mazaiting.rtda;

import com.mazaiting.rtda.heap.MtObject;

/**
 * 操作数栈
 *
 * @author mazaiting
 * @since 2021/8/13
 */
public class MtOperandStack {
    /**
     * 用于记录栈顶位置
     */
    private int size;
    /**
     * 值/引用数组
     */
    private MtSlot[] slots;

    public MtOperandStack(int maxStack) {
        if (maxStack > 0) {
            this.slots = new MtSlot[maxStack];
        }
    }

    /**
     * 压入整型值
     *
     * @param value 值
     */
    public void pushInt(int value) {
        this.slots[size] = new MtSlot();
        this.slots[size].setNum(value);
        this.size++;
    }

    /**
     * 弹出整型值
     *
     * @return 整型值
     */
    public int popInt() {
        this.size--;
        int num = slots[size].getNum();
        this.slots[size] = null;
        return num;
    }

    /**
     * 压入单精度值
     *
     * @param value 值
     */
    public void pushFloat(float value) {
        this.slots[size] = new MtSlot();
        this.slots[size].setNum(Float.floatToIntBits(value));
        this.size++;
    }

    /**
     * 弹出单精度值
     *
     * @return 单精度值
     */
    public float popFloat() {
        this.size--;
        int num = slots[size].getNum();
        this.slots[size] = null;
        return Float.intBitsToFloat(num);
    }

    /**
     * 压入long值
     *
     * @param value 值
     */
    public void pushLong(long value) {
        this.slots[size] = new MtSlot();
        this.slots[size + 1] = new MtSlot();
        this.slots[size].setNum((int) value);
        this.slots[size + 1].setNum((int) (value >> 32));
        this.size += 2;
    }

    /**
     * 弹出long值
     *
     * @return long值
     */
    public long popLong() {
        this.size -= 2;
        int lower = slots[size].getNum();
        int high = slots[size + 1].getNum();
        this.slots[size] = null;
        this.slots[size + 1] = null;
        return (((long) high << 32) & 0xFFFFFFFF00000000L) | ((long) lower & 0xFFFFFFFFL);
    }

    /**
     * 压入double值
     *
     * @param value 值
     */
    public void pushDouble(double value) {
        pushLong(Double.doubleToLongBits(value));
    }

    /**
     * 弹出double值
     *
     * @return double值
     */
    public double popDouble() {
        return Double.longBitsToDouble(popLong());
    }

    /**
     * 压入引用类型数据
     *
     * @param ref 引用
     */
    public void pushRef(MtObject ref) {
        this.slots[size] = new MtSlot();
        this.slots[size].setRef(ref);
        this.size++;
    }

    /**
     * 弹出引用
     *
     * @return 引用值
     */
    public MtObject popRef() {
        this.size--;
        MtObject ref = slots[size].getRef();
        // 弹出引用后设置为空
        this.slots[size] = null;
        return ref;
    }

    /**
     * 压入槽
     *
     * @param slot 槽点
     */
    public void pushSlot(MtSlot slot) {
        this.slots[size] = slot;
        this.size++;
    }

    /**
     * 弹出槽
     *
     * @return 槽点
     */
    public MtSlot popSlot() {
        this.size--;
        MtSlot slot = this.slots[size];
        this.slots[size] = null;
        return slot;
    }

}


















